<template>
  <div class="info-table">
    <div class="info-table-header">信息标题</div>
    <div class="info-table-content">
      <!-- 表格 -->
      <el-table :data="currentData" style="width: 100%"  @cell-click="getSelectItem"
        @cell-contextmenu="getSelectItem" @click.right.prevent @row-contextmenu="handleRightClick">
        <el-table-column fixed prop="date" label="日期"  />
        <el-table-column prop="name" label="姓名"  />
        <!-- <el-table-column prop="state" label="State" width="120" />
        <el-table-column prop="city" label="City" width="120" />
        <el-table-column prop="address" label="Address" width="300" /> -->
        <el-table-column prop="tag" label="描述" />
        <el-table-column fixed="right" label="工具栏" >
          <template #default>
            <el-button type="primary" size="small">新增</el-button>
            <el-button type="primary" size="small">查看</el-button>
            <el-button type="primary" size="small">编辑</el-button>
            <el-button type="danger" size="small">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <!-- 弹出层 -->
      <el-dialog v-model="dialogFormVisible" :title="form.title">
        <el-form :model="form" :rules="rule" ref="ruleForm">
          <el-form-item label="机构名称" :label-width="formLabelWidth" prop="name">
            <el-input v-model="form.name" autocomplete="off" :disabled="form.nameChange" />
          </el-form-item>
          <el-form-item label="描述" :label-width="formLabelWidth">
            <el-input v-model="form.des" autocomplete="off" :disabled="form.desChange" />
            <!-- <el-select v-model="form.region" placeholder="Please select a zone">
              <el-option label="Zone No.1" value="shanghai" />
              <el-option label="Zone No.2" value="beijing" />
            </el-select> -->
          </el-form-item>
        </el-form>
        <template #footer>
          <span class="dialog-footer">
            <el-button @click="dialogFormVisible = false">取消</el-button>
            <el-button type="primary" @click="handleConfirm($refs.ruleForm)">确定</el-button>
          </span>
        </template>
      </el-dialog>
    </div>
    <div class="info-table-pagination">
      <!-- 分页器 -->
      <el-pagination layout="prev, pager, next" :total="tableData.length" :page-size="pageSize"
        @current-change="pageChange" />
    </div>
    <div id="contextmenu" v-show="menuVisible" class="contextmenu">
      <div class="contextmenu-item" @click="add">新增</div>
      <div class="contextmenu-item" @click="query">查看</div>
      <div class="contextmenu-item" @click="edit">编辑</div>
      <div class="contextmenu-item" @click="deleteData">删除</div>
    </div>
  </div>
</template>

<script>
import { computed, ref, reactive } from 'vue';
import { get } from '@/api/request'

// 当前页展示的内容
const currentPage = (number, pageSize, tableData) => {
  const result = [];
  const index = (number - 1) * pageSize;
  for (let i = index; i < index + pageSize; i++) {
    if (tableData[i]) result.push(tableData[i])
    else break
  }
  return result;
}

//分页器功能
const usePageChange = (tableData) => {

  const pageSize = 5;

  const currentPageNumber = ref(1);

  const currentData = computed(() => currentPage(currentPageNumber.value, pageSize, tableData));

  const pageChange = number => currentPageNumber.value = number;

  return { pageSize, currentData, pageChange } 
}

// 工具菜单
const useTools = (tableData, dialogFormVisible, form, toolType, currentItemNumber,currentItem,menuVisible) => {

  // 初始化弹出层
  const init = (dialogFormVisible, form, type, obj) => {
    dialogFormVisible.value = true;
    form.title = type;

    if (obj) {
      form.name = obj.name;
      form.des = obj.tag;
      if (type === '查看') form.nameChange = form.desChange = true;
      else {
        form.nameChange = form.desChange = false;
        for (let item in tableData) {
          if (tableData[item].date === obj.date) currentItemNumber.value = item
        }
      }
    }
    else {
      form.name = '';
      form.des = '';
      form.nameChange = form.desChange = false;
    }
  }

  // 删除选中项
  const deleteItem = obj => {
    console.log(obj);
    for (let item in tableData) {
      if (tableData[item].date === obj.date) tableData.splice(item, 1)
    }
  }

  // 根据type类型的不同来处理不同的情况
  const operate = (type, obj) => {
    if (type === '删除') deleteItem(obj);
    else if (type === '新增') {
      init(dialogFormVisible, form, type);
    }
    else if (type === '查看') {
      init(dialogFormVisible, form, type, obj);
    }
    else if (type === '编辑') {
      init(dialogFormVisible, form, type, obj);
    }
  }

  // 获取点击时的对象
  const getSelectItem = (...context) => {
    if (context[3].target.tagName.toLowerCase() === 'span') {
      toolType.value = context[3].target.innerText;
      operate(toolType.value,context[0])
    }
  }

  const foo = () => {
    menuVisible.value = false;
    document.removeEventListener('click',foo);
  }

  // 右键弹出层
  const handleRightClick = (...context) => {
    menuVisible.value = true;
    currentItem.value = context[0];
    const menu = document.getElementById('contextmenu');
    menu.style.left = `${context[2].clientX}px`;
    menu.style.top = `${context[2].clientY}px`;
    document.addEventListener('click',foo);
  }

  return { getSelectItem, handleRightClick, operate }
}

// 弹出层
const useDialog = (tableData, toolType, currentItemNumber) => {
  const dialogFormVisible = ref(false);
  const formLabelWidth = ref('90px');

  const form = reactive({
    title: '新增',
    name: '',
    des: '',
    nameChange: false,
    desChange: false
  })

  const validator = (rule, value, callback) => {
    const specialChar = '$：%*!~^&\\/';
    let includes = false;
    specialChar.split('').forEach(item => {
      if (value.includes(item)) includes = true;
    })
    if (includes) callback(new Error('不能包含特殊字符'));
    else callback();
  }

  const rule = {
    name: [{ validator , trigger: 'blur' }, { required: true, message: '必填', trigger: 'blur' }]
  }

  const handleConfirm = (el) => {
    el.validate(valid => {
      if (valid) {
        dialogFormVisible.value = false;
        if (toolType.value === '编辑') {
          tableData[currentItemNumber.value] = {
            date: '2016-05-17',
            name: form.name,
            state: 'California',
            city: 'Los Angeles',
            address: 'No. 189, Grove St, Los Angeles',
            zip: 'CA 90036',
            tag: form.des,
          }
        } else if (toolType.value === '新增') {
          tableData.push({
            date: '2016-05-17',
            name: form.name,
            state: 'California',
            city: 'Los Angeles',
            address: 'No. 189, Grove St, Los Angeles',
            zip: 'CA 90036',
            tag: form.des,
          })
        }
      } else {
        return false
      }
    });
  }

  return { dialogFormVisible, form, formLabelWidth, rule, handleConfirm }
}

const useMenu = (currentItem,operate) => {
  const add =() => {
    operate('新增')
  }
  const query =() => {
    operate('查看',currentItem.value)
  }
  const edit =() => {
    operate('编辑',currentItem.value)
  }
  const deleteData =() => {
    operate('删除',currentItem.value)
  }
  return {add,query,edit,deleteData}
}

export default {
  setup() {
    get('https://www.fastmock.site/mock/ae8e9031947a302fed5f92425995aa19/jd/api/shop/hot-list').then(res => console.log(res.data));

    const data = [
      {
        date: '2016-05-01',
        name: 'Tom',
        state: 'California',
        city: 'Los Angeles',
        address: 'No. 189, Grove St, Los Angeles',
        zip: 'CA 90036',
        tag: 'Home',
      },
      {
        date: '2016-05-02',
        name: 'dd',
        state: 'California',
        city: 'Los Angeles',
        address: 'No. 189, Grove St, Los Angeles',
        zip: 'CA 90036',
        tag: 'Office',
      },
      {
        date: '2016-05-03',
        name: 'fff',
        state: 'California',
        city: 'Los Angeles',
        address: 'No. 189, Grove St, Los Angeles',
        zip: 'CA 90036',
        tag: 'Home',
      },
      {
        date: '2016-05-04',
        name: 'xcv',
        state: 'California',
        city: 'Los Angeles',
        address: 'No. 189, Grove St, Los Angeles',
        zip: 'CA 90036',
        tag: 'Office',
      },
      {
        date: '2016-05-05',
        name: 'ty',
        state: 'California',
        city: 'Los Angeles',
        address: 'No. 189, Grove St, Los Angeles',
        zip: 'CA 90036',
        tag: 'Home',
      },
      {
        date: '2016-05-06',
        name: 'Tom',
        state: 'California',
        city: 'Los Angeles',
        address: 'No. 189, Grove St, Los Angeles',
        zip: 'CA 90036',
        tag: 'Office',
      },
      {
        date: '2016-05-07',
        name: 'Tom',
        state: 'California',
        city: 'Los Angeles',
        address: 'No. 189, Grove St, Los Angeles',
        zip: 'CA 90036',
        tag: 'Home',
      },
      {
        date: '2016-05-08',
        name: 'Tom',
        state: 'California',
        city: 'Los Angeles',
        address: 'No. 189, Grove St, Los Angeles',
        zip: 'CA 90036',
        tag: 'Office',
      },
      {
        date: '2016-05-09',
        name: 'Tom',
        state: 'California',
        city: 'Los Angeles',
        address: 'No. 189, Grove St, Los Angeles',
        zip: 'CA 90036',
        tag: 'Home',
      },
      {
        date: '2016-05-10',
        name: 'Tom',
        state: 'California',
        city: 'Los Angeles',
        address: 'No. 189, Grove St, Los Angeles',
        zip: 'CA 90036',
        tag: 'Office',
      },
      {
        date: '2016-05-11',
        name: 'Tom',
        state: 'California',
        city: 'Los Angeles',
        address: 'No. 189, Grove St, Los Angeles',
        zip: 'CA 90036',
        tag: 'Home',
      },
      {
        date: '2016-05-12',
        name: 'Tom',
        state: 'California',
        city: 'Los Angeles',
        address: 'No. 189, Grove St, Los Angeles',
        zip: 'CA 90036',
        tag: 'Office',
      },
      {
        date: '2016-05-13',
        name: 'Tom',
        state: 'California',
        city: 'Los Angeles',
        address: 'No. 189, Grove St, Los Angeles',
        zip: 'CA 90036',
        tag: 'Home',
      },
      {
        date: '2016-05-14',
        name: 'Tom',
        state: 'California',
        city: 'Los Angeles',
        address: 'No. 189, Grove St, Los Angeles',
        zip: 'CA 90036',
        tag: 'Office',
      },
      {
        date: '2016-05-15',
        name: 'Tom',
        state: 'California',
        city: 'Los Angeles',
        address: 'No. 189, Grove St, Los Angeles',
        zip: 'CA 90036',
        tag: 'Home',
      },
      {
        date: '2016-05-16',
        name: 'Tom',
        state: 'California',
        city: 'Los Angeles',
        address: 'No. 189, Grove St, Los Angeles',
        zip: 'CA 90036',
        tag: 'Office',
      },
    ]

    // 点击工具菜单的类型
    const toolType = ref('');

    // 点击工具菜单所对应的数据序号
    const currentItemNumber = ref(0);

    // 右键当前的数据
    const currentItem = ref('');

    // 右键菜单控制显示
    const menuVisible = ref(false);

    const tableData = reactive(data);

    const { pageSize, currentData, pageChange } = usePageChange(tableData);

    const { dialogFormVisible, form, formLabelWidth, rule, handleConfirm } = useDialog(tableData, toolType, currentItemNumber);

    const { getSelectItem, handleRightClick ,operate} = useTools(tableData, dialogFormVisible, form, toolType, currentItemNumber,currentItem,menuVisible);

    const {add,query,edit,deleteData} = useMenu(currentItem,operate);

    return { getSelectItem, handleRightClick, pageChange, handleConfirm, currentData, pageSize, tableData, dialogFormVisible, form, formLabelWidth, rule,menuVisible,add,query,edit,deleteData }

  }
}
</script>

<style scoped lang="scss">
.info-table {
  display: flex;
  flex-direction: column;

  &-pagination {
    align-self: center;
  }
}
.contextmenu{
  position: absolute;
  width: 100px;
  line-height: 30px;
  border: 1px solid #e9e9e9;
  background-color: #fff;
  z-index: 9;
  &-item + &-item{
    border-top: 1px solid #e9e9e9;
  }
  &-item:hover{
    background-color: #e9e9e9;
    cursor: pointer;
  }
}
</style>